#include "io_CParser.h"
#include <stdio.h>

#include "../mem/mem_manager.h"
#include "io_console.h"

CParser::CParser()
{
	data = NULL;
	dataLen = 0;
	dataPos = 0;
}

CParser::~CParser()
{
	g_free(data);
}

int CParser::open(const char *fname)
{	
	long len;

	FILE *f = fopen(fname,"rb");

	if (!f)
		return ERR_FILENOTFOUND;

	fseek(f,0,SEEK_END);
	len = ftell(f);
	fseek(f,0,SEEK_SET);
	if (len>=MAX_FILE_SIZE)
		return ERR_FILETOOBIG;

	g_allocv(data, char, len);

	fread(data, len, 1, f);

	fclose(f);

	dataPos = 0;
	dataLen = (int)len;
	return PARSER_CONTINUE;
}

bool CParser::isTokenChar(char c)
{
	return (((c>='A')&&(c<='Z'))||((c>='a')&&(c<='z'))||((c>='0')&&(c<='9'))||(c=='_')||(c=='.')||(c=='-'));
}

bool CParser::isWhiteChar(char c)
{
	return ((c==' ')||(c=='\t')||(c=='\n')||(c=='\r'));
}

int CParser::tokenLen()
{
	int oldPos = dataPos;

	while (hasMore() && isTokenChar(data[dataPos]))
		dataPos++;

	int len = dataPos - oldPos;
	dataPos = oldPos;

	return len;
}

int CParser::readToken(char *buf, int maxLen)
{
	int len = tokenLen();

	if (len>maxLen)
		len = maxLen;

	strncpy(buf, data+dataPos, len);
	if (len<maxLen)
		buf[len] = 0;

	dataPos += len;

	return len;
}

char* CParser::readToken()
{
	int len = tokenLen();
	char *buf;

	g_allocv(buf, char, len+1);
	strncpy(buf, data+dataPos, len);
	buf[len] = 0;

	dataPos += len;

	return buf;
}

int CParser::skipComments()
{
	int oldPos = dataPos;
	//skip one-line comments
	if (hasMore(2) && (data[dataPos] == '/') &&( data[dataPos+1] == '/'))
	{
		while (hasMore() && (data[dataPos] != '\n') && (data[dataPos] != '\r'))
			dataPos++;
	}

	if (hasMore(2) && (data[dataPos] == '/') &&( data[dataPos+1] == '*'))
	{
		while (hasMore(2) && (data[dataPos] != '*') && (data[dataPos] != '/'))
			dataPos++;

		if ((data[dataPos] != '*') || (data[dataPos] != '/'))
			return ERR_PARSEERROR;

		dataPos+=2;
	}

	return dataPos - oldPos;
}

int CParser::skipWhiteSpace()
{
	int oldPos = dataPos;

	while (hasMore() && isWhiteChar(data[dataPos]))
		dataPos++;

	return dataPos - oldPos;
}

int CParser::skipAll()
{
	int skipped = 1;

	while (skipped)
	{
		skipped  = skipWhiteSpace();
		skipped += skipComments();

		if (eof())
			return ERR_ENDOFFILE;

	}
	return PARSER_CONTINUE;
}

bool CParser::eof()
{
	return (!hasMore());
}

bool CParser::hasMore(int c)
{
	return (dataPos+c<=dataLen);
}